#ifndef MODEL_HPP
#define MODEL_HPP

#include "Observer.hpp"
#include "Tree.hpp"
#include "Node.hpp"

#include <stack>

class Model
{
private :
    Observer* _observer;
    Tree* _workingTree;
    std::stack<Tree*> _cancelledTrees;
    std::stack<Tree*> _previousTrees;

public:
    Model();

    void pushOldTree();
    void undo();
    void redo();
    bool canUndo() const;
    bool canRedo() const;

    void setObserver(Observer* observer);

    const std::vector<Node*> getNodes(int startX, int startY,
                                      int endX, int endY) const;
    void addNodesToSelection(const std::vector<Node*>& selectedNodes);
    void clearSelection();

    bool canAddChildToSelection();
    bool canAddSiblingToSelection() const;

    bool canChangeSelectionSettings() const;
    void changeSelectionSettings(const std::string & newName, Node::NodeType newType);

    bool isSelectionDeletable() const;
    void deleteSelection();

    void addChildToSelection();
    void addSiblingToSelection();

    const Tree* const getWorkingTree() const;

    const Node* const getSelection() const;
    void selectNode(int x, int y);

    void moveSelectedNodesGraphically(int dx, int dy);
    bool areSelectedNodesMovableGraphically();

    bool canRedrawSubtree() const;
    void redrawTree();

    void manageIterative();
    void manageOptional();

    bool canChangeSelectionRelationType() const;
    void setSelectionRelationType(Node::RelationType rType);

    void save();
    void open();
    void newtree();

};

#endif // MODEL_HPP
